﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LcfContols
{

    /// <summary>
    /// 自定义下拉控件框
    /// </summary>
    public class LComboBox : ComboBox
    {
        #region 属性
        /// <summary>
        /// 下拉项
        /// </summary>
        private LEventList<LComboBoxItem> _items = new LEventList<LComboBoxItem>();
        /// <summary>
        /// 下拉项增加事件
        /// </summary>
        public event LComboBoxItemEvent ItemAdd;
        /// <summary>
        /// 移除下拉项事件
        /// </summary>
        public event LComboBoxItemEvent ItemRemove;
        /// <summary>
        /// 是否将不存在的内容输入放入到下拉项
        /// </summary>
        private bool _isAddInput = false;
        #endregion

        public new LEventList<LComboBoxItem> Items
        {
            get { return _items; }
        }

        [Description("是否将输入的信息加入下拉项中")]
        public bool isAddInput
        {
            get
            {
                return _isAddInput;
            }
            set
            {
                _isAddInput = value;
                if (value)
                {
                    this.KeyPress -= MyCombox_KeyPress;
                    this.TextUpdate -= MyCombox_TextUpdate;
                    this.KeyPress += MyCombox_KeyPress2;
                    this.TextUpdate += MyCombox_TextUpdate2;
                }
                else
                {
                    this.KeyPress += MyCombox_KeyPress;
                    this.TextUpdate += MyCombox_TextUpdate;
                    this.KeyPress -= MyCombox_KeyPress2;
                    this.TextUpdate -= MyCombox_TextUpdate2;
                }
            }
        }

        public LComboBox()
        {
            _items.AddEvent += _items_AddEvent;
            _items.RemoveEvent += _items_RemoveEvent;
            _items.ClearEvent += _items_ClearEvent;
            this.KeyPress += MyCombox_KeyPress;
            this.TextUpdate += MyCombox_TextUpdate;
        }

        private void _items_ClearEvent(object obj)
        {
            base.Items.Clear(); //父级也移除掉
        }

        private void _items_RemoveEvent(object arg1, int arg2, LComboBoxItem arg3)
        {
            base.Items.RemoveAt(arg2);
            if(ItemRemove != null)
            {
                ItemEventArgs eventArg = new ItemEventArgs();
                eventArg.NewIndex = -1;
                eventArg.OldIndex = arg2;
                eventArg.Item = arg3;
                ItemRemove(this, eventArg);
            }
        }

        private void _items_AddEvent(object arg1, int arg2)
        {
            LComboBoxItem item = ((LEventList<LComboBoxItem>)arg1)[arg2];
            if (String.IsNullOrWhiteSpace(item.Search))
            {
                item.Search = Pinyin.GetStringSpell(item.Display);
            }
            base.Items.Add(item);
            if (ItemAdd != null)
            {
                ItemEventArgs eventArg = new ItemEventArgs();
                eventArg.NewIndex = arg2;
                eventArg.OldIndex = -1;
                eventArg.Item = _items[arg2];
                ItemAdd(this, eventArg);
            }
        }

        private void MyCombox_TextUpdate(object sender, EventArgs e)
        {
            if (!searchInItem(Text))
            {
                Text = string.Empty;
                result();
                return;
            }
            searchItemstr(Text);
        }

        private void MyCombox_TextUpdate2(object sender, EventArgs e)
        {
            searchItemstr(Text);
        }

        private void MyCombox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter && base.Items.Count > 0 && this.SelectedIndex < 0)
                this.SelectedIndex = 0;
        }

        private void MyCombox_KeyPress2(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
                _items.Add(new LComboBoxItem(Text));
        }

        protected void searchItemstr(string s)
        {
            LComboBoxItem[] i = search(s);
            this.DroppedDown = i.Length > 0;
            base.Items.Clear();
            base.Items.AddRange(i);
            this.SelectionStart = this.Text.Length;
        }

        /// <summary>
        /// 搜索字符串是否在下拉项中 
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public bool searchInItem(string s)
        {
            return search(s).Length > 0;
        }

        /// <summary>
        /// 设置选择值
        /// </summary>
        /// <param name="s"></param>
        public void SetValue(string s)
        {
            LComboBoxItem[] its = _items.Where(x => x.Value.ToString().IndexOf(s, StringComparison.CurrentCultureIgnoreCase) != -1).ToArray();
            SelectedIndex = _items.IndexOf(its[0]);
        }

        /// <summary>
        /// 搜索和参数字符串相同的下拉项目
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        private LComboBoxItem[] search(string s)
        {
            return _items.Where(x => x.Search.IndexOf(s, StringComparison.CurrentCultureIgnoreCase) != -1 ||
                x.Display.IndexOf(s, StringComparison.CurrentCultureIgnoreCase) != -1).ToArray();
        }

        /// <summary>
        /// 返回选中项的值
        /// </summary>
        /// <returns></returns>
        public object Value {
            get
            {
                if (Items.Count < 1)
                    return "";
                else if (SelectedIndex < 0)
                {
                    SelectedIndex = 0;
                }
                return (base.Items[SelectedIndex] as LComboBoxItem)?.Value;
            }
        }
        
        public new LComboBoxItem SelectedItem
        {
            get
            {
                return base.SelectedItem as LComboBoxItem;
            }
        }

        /// <summary>
        /// 重置Items
        /// </summary>
        internal void result()
        {
            base.Items.Clear();
            base.Items.AddRange(_items.ToArray());
        }

        /// <summary>
        /// Item变动事件
        /// </summary>
        public class ItemEventArgs : EventArgs
        {
            /// <summary>
            /// 新索引
            /// </summary>
            public int NewIndex { get; internal set; }
            /// <summary>
            /// 旧索引
            /// </summary>
            public int OldIndex { get; internal set; }
            /// <summary>
            /// 相关Item
            /// </summary>
            public LComboBoxItem Item { get; internal set; }
        }
    }
    
    /// <summary>
    /// LComboBox中下拉项变动时间代理
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void LComboBoxItemEvent(object sender, LComboBox.ItemEventArgs e);
}
